import xID from "./xID.js";
import {findJsonByCode} from "./treeUtil.js";
import  cell  from "./cell.js";

const tmplBase = `
        <div  class="{{class}}" tabindex="0">
             <div type="head" class="xhead">   
                  <input key ="input" class="xinput-icon" readonly />   
                  <i class="iconfont icon-close after-icon-set hover" style ="display: none" title="清除" type="clear"></i>               
                  <i class="iconfont icon-dropdown after-icon-set" type="drop"></i> 
             </div> 
             <div type="main" style="display:none" class="xmain">
                 <div type="search">
                      <input placeholder="搜索..." key="search" tabindex="-1">
                      <i class="iconfont icon-search"></i>
                 </div>
                 <div type="body">
                 </div>
                 <div type="spin" class=" p-2 " style="display:none;text-align: center"> 
                    <span class="spinner-grow spinner-grow-sm text-danger" ></span>
                 </div>               
             </div>
        </div>`;



export default class xSelect {
    /* 定义变量 开始*/
    // jquery 对象

    $root;
    $head;
    $main;
    $body;
    $input;
    vBindEvent;
    vTmpEvent ={};
    vCfg;
    vSelect;
    vData;
    vFilter;
    vClickId = 'click.'+xID.getID();
    vDropActive=-1;

    /* 定义变量 结束*/

    constructor(cfg) {
        this.$root = $('#' + cfg.el);
        this.$root.html(tmplBase.replace('{{class}}', cfg.style||'select'));
        this.vCfg = cfg;
        this.init();
    };

    /* 渲染区块 开始 */
    init() {
        this.$head = this.$root.find('[type="head"]');
        this.$main = this.$root.find('[type="main"]');
        this.$body = this.$root.find('[type="body"]');

        this.$input = this.$root.find('input[key="input"]');
        this.$search = this.$root.find('input[key="search"]');
        this.$root.on('focus',">div",this.evFocus.bind(this));
        this.$root.on('click', this.evRootClick.bind(this));
        this.$root.on('click','i[type="clear"]',this.evClear.bind(this));
        this.$search.on('input',this.evInput.bind(this));
        this.$root.on('keydown',this.evKeydown.bind(this));
        this.$root.on('click','label[type="select-item"]',this.evItemClick.bind(this));
        let title ='';
        if(this.vCfg.title)
            title = tmplTitle.replace("{{title}}",this.vCfg.title);
        this.$head.attr("title",title);
        if(this.vCfg.placeholder)
            this.$input.attr("placeholder",this.vCfg.placeholder);
        if(this.vCfg.active)
            this.initValue(this.vCfg.active);
    };

    renderStatus(action,status){
        if(action=='add'){
            this.$head.addClass(status);
        }else{
            this.$head.removeClass(status);
        }
    }

    initValue(value){
        /*
        if((this.vCfg.valueType||'code') =='code'){
            if(this.vCfg.multiple){
                this.vSelect = [];
                let tmp = (value||'').split(',');
                tmp.forEach(code => this.vSelect.push(findJsonByCode(this.vCfg.data,code)));
            }else{
                this.vSelect =[]
                let obj = findJsonByCode(this.vCfg.data,value);
                if(obj)
                    this.vSelect.push(obj);
            }

        }
        else
            this.vSelect =  value?value:[];
        */

        if(value){
            if((this.vCfg.valueType||'code') =='code'){
                if(this.vCfg.multiple){
                    this.vSelect = [];
                    let tmp = (value||'').split(',');
                    tmp.forEach(code => this.vSelect.push(findJsonByCode(this.vCfg.data,code)));
                }else{
                    let obj = findJsonByCode(this.vCfg.data,value);
                    if(obj)
                        this.vSelect = obj;
                }
            }else{
                this.vSelect = value;
            }
        }else
            this.vSelect = this.vCfg.multiple?[]:{};
        let val;
        if(this.vCfg.multiple){
            let tmpArray = [];
            this.vSelect.forEach( d => tmpArray.push(d.name||d.code) );
            val = tmpArray.join(',');
        }else
           val = this.vSelect?(this.vSelect.name||this.vSelect.code||''):'';
        this.$input.val(val);
        this.renderIcon();
        this.verify();
    }

    mainShow(){
        this.renderBody();
        this.renderIcon();
        this.$main.show();
    }

    renderBody(){
        this.$body.html(cell.renderSelectList({...this.vCfg,data:this.filter()}));
    }

    renderSelected(){
        if(this.vSelect){
            let selected=[];
            if(this.vCfg.multiple)
                this.vSelect.forEach(item => selected.push(item.code+''));
            else
                selected.push(this.vSelect.code+'');

            this.$root.find('label[type="select-item"]').each((index,el) =>{
                let code = el.getAttribute("data-code");
                if(selected.includes(code))
                    $(el).addClass("selected");
                else
                    $(el).removeClass("selected");
            });
        }else{
            this.$root.find('label[type="select-item"]').each((index,el) =>{
                    $(el).removeClass("selected");
            })
        }
    }

    renderIcon(){
        let $drop = this.$root.find('i[type="drop"]');
        let $clear = this.$root.find('i[type="clear"]');
        let nonSelect = true;
        if(this.vCfg.multiple){
            nonSelect = this.vSelect&&this.vSelect.length>0;
        }else
            nonSelect =!!this.vSelect;
        if(nonSelect){
            $drop.hide();
            $clear.show();
        }else{
            $drop.show();
            $clear.hide();
        }
    }

    filter(){
        let result = [];
        let ok;
        let input = this.$search.val();
        let _this = this;
        this.vCfg.data.forEach(item => {
            ok = 0;
            if(_this.vFilter){
                if(item[_this.vFilter.key] == _this.vFilter.value)
                    ok = ok +1;
            }else
                ok = ok +1;

            if(input){
                if((item.pinyin && item.pinyin.toLowerCase().indexOf(input.toLowerCase())>-1)
                    || item.name.indexOf(input)>-1 ){
                    ok = ok +1;
                }
            }else
                ok = ok + 1 ;

            if(ok==2)
                result.push(item);
        })

        return result;
    };

    selected(code,isSelected){
        let item = findJsonByCode(this.vCfg.data,code);
        if(this.vCfg.multiple){
            if(isSelected)
                this.vSelect = this.vSelect.filter( d => d.code != item.code );
            else{
                if(!this.vSelect)
                    this.vSelect = [];
                this.vSelect.push(item);
            }

            let values=[];
            this.vSelect.forEach(d => values.push(d.name));
            this.$input.val(values.join(','));
            this.renderIcon();
            this.renderSelected();
            this.sync();
        }else{
            this.vSelect = item;
            this.$input.val(this.vSelect.name);
            this.renderIcon();
            this.renderSelected();
            this.sync();
        }

    }

    active(){
        this.renderBody();
        this.renderSelected();
        this.$search.val('');
        this.renderStatus("add","active");
        this.$main.show();
        this.$search.focus();
        this.vDropActive = -1;
        $(document).on(this.vClickId,this.evOff.bind(this));
    }

    evFocus(e){
        if(this.$main.is(':visible'))
            return;
        let _this = this;
        function cbLoadSuccess(data){
            _this.setData(data);
            _this.$main.find('div[type="body"]').show();
            _this.$main.find('div[type="search"]').show();
            _this.$main.find('div[type="spin"]').hide();

        }
        if(this.vCfg.load){
            this.$main.find('div[type="body"]').hide();
            this.$main.find('div[type="search"]').hide();
            this.$main.find('div[type="spin"]').show();
            this.vCfg.load(cbLoadSuccess);
        }else{
            this.active();
        }

    }

    evItemClick(e){
        let code =e.currentTarget.getAttribute("data-code");
        let isSelected = $(e.currentTarget).hasClass("selected");
        this.selected(code,isSelected);
        if(!this.vCfg.multiple)
            this.$main.hide();
    };

    evRootClick(e){
        this.vTmpEvent.timeStamp = e.timeStamp;
        this.vTmpEvent.target =e.target;

    };

    evClear(e){
        this.vSelect = [];
        this.renderSelected();
        this.$input.val('');
        this.renderIcon();
        this.sync();
    };

    evInput(e){
        this.renderBody();
        this.renderSelected();
    }

    evKeydown(e){
        let keynum = window.event ? e.keyCode : e.which;
        switch(keynum){
            //enter
            case 13:
                if(this.$main.is(':visible') && this.vDropActive>-1){
                    let all = this.$body.find('li.item');
                    let $item = $(all[this.vDropActive]).find("label")
                    let code = $item.attr("data-code");
                    let isSelected = $item.hasClass("selected");
                    this.selected(code,isSelected);
                    if(!this.vCfg.multiple){
                        this.$input.focus();
                        this.$main.hide();
                    }
                }
                break;
                //up
            case 38:
                //down
            case 40:
                this.activeItem(keynum);
                break;
            //tab 失去焦点
            case 9:
                this.evOff(e);
                break;
            case 27:
                this.$input.focus();
                this.$main.hide();
                break;
        }
    }

    evOff(e){
        if((e.type=='keydown'||
                (e.type=='click' && (this.vTmpEvent.timeStamp !=e.timeStamp || this.vTmpEvent.target !=e.target)))){
            this.$main.hide();
            this.renderStatus('remove','active');
            this.verify();
            $(document).unbind(this.vClickId);
        }
    }

    activeItem(keynum){
        let all = this.$body.find('li.item');
        //let index;
        let oldIndex =-1;
        if(this.vDropActive<0){
            this.vDropActive = keynum==38?all.length-1:0
        }
        else{
            oldIndex = this.vDropActive;
            this.vDropActive = keynum==38?this.vDropActive-1:this.vDropActive+1;
            this.vDropActive =this.vDropActive%all.length;
            if(this.vDropActive<0)
                this.vDropActive = all.length+this.vDropActive;
        }

        if(oldIndex>-1){
            $(all[oldIndex]).removeClass("active");
        }
        $(all[this.vDropActive]).addClass("active");
        let Y= all[this.vDropActive].offsetTop-this.$body[0].offsetTop;
        this.$body.scrollTop(Y);
    }

    matchData(){
        let val = this.$input.val().toLowerCase() ;
        if(val){
           let data = [] ;
           if(this.vCfg.data){
               for(let d of this.vCfg.data){
                   if(d.type!='tag'){
                       let ok =false;
                       if((d.name||d.code).toLowerCase().match(val))
                           ok = true;
                       if(d.pinyin && d.pinyin.toLowerCase().match(val))
                           ok = true;
                       if(ok)
                           data.push(d);
                   }

               }
           }
           return data;
        }
        else
            return this.vCfg.data;
    }

    setBindEvent(event){
        this.vBindEvent = event;
    };

    setValue(value){
        this.initValue(value);
    };

    setData(data){
        this.vCfg.data =data;
        this.renderBody();
    }

    setFilter(key,value){
        if(!this.vFilter)
            this.vFilter ={};
        this.vFilter.key = key;
        this.vFilter.value = value;
    }

    clearFilter(){
        this.vFilter = null;
    }

    sync(){
        if(this.vBindEvent){
            if((this.vCfg.valueType||'code') =='code'){
                if(this.vCfg.multiple){
                    let values = [];
                    this.vSelect.forEach(d => values.push(d.code));
                    this.vBindEvent(values.join(','));
                }
                else{
                    this.vBindEvent(this.vSelect.code)
                }

            }

            else
                this.vBindEvent(this.vSelect);
        }
    }

    verify() {
        let result = true;
        if(this.vCfg.mandatory ){
            if(!this.vSelect || this.vSelect.length<1){
                this.renderStatus("remove",'valid');
                this.renderStatus("add","invalid");
                result =false
            }else {
                this.renderStatus("remove",'invalid');
                this.renderStatus("add","valid");
            }
        }
        return result;
    }

    getSelect(){
        return this.vSelect;
    }

}